<title>RPC</title>
<body bgcolor="#ffffcc">
<hr>
<center><h1>Remote Procedure Calls (RPC).</h1></center>
<hr>
In the normal scope of things, a program can only call a function
that is linked into the executable or provided by a shared library.
RPC allows programs to execute functions in another executing program, cool!
<p>
RPC has a concept of clients and servers.
<ol>
<li>The client issues requests to the server.
<li>Servers perform the requests and return the results.
<li>The data that flows between client and server includes
int, float, strings and structures.
<li>The client and server can be on the same host or different hosts
connected via a network.
<li>The hosts do not have to be the same artitechture.
</ol>

The RPC <a href=../glossary.html#api>API</a> has three levels of support.
By using the highest level
RPC is responcable for most of the code but is not too flexable. The lowest
level requres more coding but gives the programmer more control over how RPC
functions.
<p>
The easiest way to start with RPC is to use a program called <b>rpcgen</b>
this reads a file that describes the required interface between client and server
and generates C code that you can include in your client and server.

<pre>

	prog.x --> rpcgen ---> prog.h        Header file
                          ---> prog_clnt.c   Client stubs file
                          ---> prog_svc.c    Server stubs file
                          ---> prog_xdr.c    XDR routines (more later).

</pre>
You write <b>prog.x</b> and rpcgen generates
<b>prog.h prog_clnt.c prog_svc.c prog_xdr.c</b>

You then write the client and server and link them with the rpcgen code
to complete the RPC system.

<pre>

	client.c    -----> client executable
        prog.h      ---|
        prog_clnt.c ---|
        prog_xdr.c  ---|

        server.c    -----> Server executable
        prog.h      ---|
        prog_svc.c  ---|
        prog_xdr.c  ---|


</pre>

Ok, time for some examples.

<h3>Calling an RPC server function without passing any arguments.</h3>
This is the simplest form of RPC.

<p>
<center>
<table bgcolor=ivory width=80%>
<th>
void.x
</th>
<tr>
<td>
<pre>

  /* RPCGEN code decribing the client/server API. */
 
  program MJLPROG
  {
    version MJLVERS
    {
      void VOID(void) = 1;
    
    } = 1;
  } = 0x20000001;
</pre>
</td>
</tr>
</table>
</center>
<p>

<b>void.x</b> describes the RPC interface between the client
and server. There are some important items to note here.
<p>
<table><tr>
<td bgcolor=silver>
<pre>
program MJLPROG
{
} = 0x20000001;
</pre></td>
<td>This is the RPC program number. It is used by the client to
identify the server it intends to use.
It is important that you provide a unique number here. You can see
which values are in use with the Unix command <b>rpcinfo -p</b> or
by looking at <b>/etc/rpc</b>. Please note that the number is supplied
in void.x as a hex value but shown as a decimal value by <b>rpcinfo</b>
One other point, you should only use values in the range 0x20000000
0x3FFFFFFF as these have been reserved for use local use.
</td>
</tr>
<tr>
<td bgcolor=silver>
<pre>
version MJLVERS
{
} = 1;
</pre></td>
<td>The RPC Version number.</td>
</tr>
<tr>
<td bgcolor=silver><pre>void VOID(void) = 1;</pre></td>
<td>This defines the only RPC function that the server will provide.</td>
</tr>
</table>
<p>

<center>
<table bgcolor=ivory width=80%>
<th>
void_client.c
</th>
<tr>
<td>
<pre>

  #include &lt;rpc/rpc.h&gt;
  #include "void.h"

  main()
  {
      CLIENT *pclnt;
      void   *pVoid;
    
      char    Host[256];

      /* Get the name of the host running the server. */
    
      gethostname(Host, 256);

      /* Connect to the server. */
    
      pclnt = clnt_create(Host, MJLPROG, MJLVERS, "udp");

      /* Issue a request to the server. */
    
      void_1(pVoid, pclnt);

      /* Disconnect from the server. */
    
      clnt_destroy(pclnt);

  }
</pre>
</td>
</tr>
</table>
</center>

<p>
<table>
<tr>
<td bgcolor=silver>
<pre>
#include &lt;rpc/rpc.h&gt;

</pre>
</td>
<td>
Include the standard RPC headers.
</td>
</tr>
<tr>
<td bgcolor=silver>
<pre>
#include "void.h"
</pre>
</td>
<td>
Include the header file generated by <b>rpcgen</b>
</td>
</tr>
<tr>
<td bgcolor=silver>
<pre>
pclnt = clnt_create();
</pre>
</td>
<td>Connect to the server <b>MJLPROG</b> on <b>Host</b> and return a
pointer to the <b>CLIENT</b> control structure.
</td>
</tr>
<tr>
<td bgcolor=silver>
<pre>
void_1(pVoid, pclnt);
</pre>
</td>
<td>
Call the remote function.
</td>
</tr>
<tr>
<td bgcolor=silver>
<pre>
clnt_destroy();
</pre>
</td>
<td>
Disconnect from the server.
</td>
</tr>
</table>
<p>

<center>
<table bgcolor=ivory width=80%>
<th>
void_server.c
</th>
<tr>
<td>
<pre>

  #include <rpc/rpc.h>
  #include "void.h"

  void *void_1_svc(void *pVoid,  struct svc_req *X)
  {
      printf("Function called without passing arguments\n");
  }

</pre>
</td>
</tr>
</table>
</center>

<p>
<table>
<tr>
<td bgcolor=silver>
<pre>
void *void_1_svc()
</pre>
</td>
<td>
The server function that will be run for the client.
</td>
</tr>
</table>
<p>

Please note that the server does not have a <b>main()</b>, rpcgen
generates it for you.
<p>
The code can be compiled with the following commands

<pre>
  gcc void_server.c void_svc.c -o void_server
  gcc void_client.c void_clnt.c -o void_client
</pre>
<p>
In theory you should be able to start the server and it will
respond everytime the client is  executed. I have not included any
error recovery into this example as it makes the code harder to
read. As an exercise try adding the error recovery code yourself :-)

<h3>Transfer integers between the client and server</h3>


<p>
<center>
<table bgcolor=ivory width=80%>
<th>
integer.x
</th>
<tr>
<td>
<pre>

  /* RPCGEN code decribing the client/server API. */
 
  program MJLPROG
  {
    version MJLVERS
    {
      int INTEGER(int) = 1;
    
    } = 1;
  } = 0x20000001;
</pre>
</td>
</tr>
</table>
</center>

<p>
<table>
<tr>
<td bgcolor=silver>
<pre>
int INTEGER(int) = 1;
</pre>
</td>
<td>
Server function now accepts an integer and returns an integer.
</td>
</tr>
</table>




<p>

<hr>
<h2>See Also:</h2>

<img src=../../GRAPHICS/whiteball.gif>
<a href=../SYNTAX/void.html>VOID keyword.</a>
<hr>
<p>
<center>
<table border=2 width=80% bgcolor=ivory>
<tr align=center>
<td width=25%>
<a href=../cref.html>Top</a>
</td><td width=25%>
<a href=../master_index.html>Master Index</a>
</td><td width=25%>
<a href=../SYNTAX/keywords.html>Keywords</a>
</td><td width=25%>
<a href="../FUNCTIONS/funcref.htm">Functions</a>
</td>
</tr>
</table>
</center>
<p>
 
<hr>
29-Dec-97
<address><a href=../../address.html>Martin Leslie</a>



